package com.mofum.msdom.excel.annotation.parser.impl;

import com.mofum.msdom.excel.annotation.ATSheet;
import com.mofum.msdom.excel.annotation.ATWorkbook;
import com.mofum.msdom.excel.annotation.parser.AnnotationParser;
import com.mofum.msdom.excel.metadata.MPSheet;
import com.mofum.msdom.excel.metadata.MPWorkbook;
import com.mofum.msdom.excel.utils.ReflectUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * AT 工作薄注解解析器
 *
 * @author 1615690513@qq.com
 * @since 2018/11/21 0021 15:13
 */
public class ATWorkbookParser<T> implements AnnotationParser<T, MPWorkbook> {

    public Map<Field, MPWorkbook> parseField(T o) {

        Map<Field, MPWorkbook> map = new HashMap<Field, MPWorkbook>();

        Field[] fields = ReflectUtils.convertToClass(o).getDeclaredFields();

        for (Field field : fields) {

            if (field.isAnnotationPresent(ATWorkbook.class)) {

                ATWorkbook atWorkbook = field.getAnnotation(ATWorkbook.class);

                map.put(field, parse(atWorkbook));

            }

        }

        return map;
    }

    public Map<Type, MPWorkbook> parseType(T o) {

        Map<Type, MPWorkbook> map = new HashMap<Type, MPWorkbook>();

        Class<T> clazz = ReflectUtils.convertToClass(o);

        if (clazz.isAnnotationPresent(ATWorkbook.class)) {

            ATWorkbook atWorkbook = clazz.getAnnotation(ATWorkbook.class);

            map.put(clazz, parse(atWorkbook));

        }

        return map;
    }

    public Map<Method, MPWorkbook> parseMethod(T o) {

        Map<Method, MPWorkbook> map = new HashMap<Method, MPWorkbook>();

        Method[] methods = ReflectUtils.convertToClass(o).getDeclaredMethods();

        for (Method method : methods) {

            if (method.isAnnotationPresent(ATWorkbook.class)) {

                ATWorkbook atWorkbook = method.getAnnotation(ATWorkbook.class);

                map.put(method, parse(atWorkbook));

            }

        }

        return map;
    }

    public Map<Method, List<MPWorkbook>> parseParams(T o) {

        Map<Method, List<MPWorkbook>> map = new HashMap<Method, List<MPWorkbook>>();

        Method[] methods = ReflectUtils.convertToClass(o).getMethods();

        for (Method method : methods) {

            List<MPWorkbook> list = new ArrayList<MPWorkbook>();

            Annotation[][] parameterAnnotations = method.getParameterAnnotations();

            for (Annotation[] parameterAnnotation : parameterAnnotations) {
                for (Annotation annotation : parameterAnnotation) {
                    if (annotation instanceof ATWorkbook) {
                        ATWorkbook atWorkbook = (ATWorkbook) annotation;
                        list.add(parse(atWorkbook));
                    }
                }
            }

            map.put(method, list);
        }

        return map;
    }

    public MPWorkbook parse(ATWorkbook atWorkbook) {

        MPWorkbook mpWorkbook = new MPWorkbook();

        mpWorkbook.setCache(atWorkbook.cache());

        mpWorkbook.setName(atWorkbook.name());

        ATSheetParser<MPSheet> parser = new ATSheetParser<MPSheet>();

        List<MPSheet> list = new ArrayList<MPSheet>();

        for (ATSheet atSheet : atWorkbook.sheets()) {
            list.add(parser.parse(atSheet));
        }

        mpWorkbook.setSheets(list.toArray(new MPSheet[]{}));

        return mpWorkbook;
    }
}
